<?php

namespace App\Entity;

use App\Event\UserChangeEvent;
use App\EventSubscriber\UserSubscriber;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use ApiPlatform\Core\Annotation\ApiResource;
use Symfony\Component\EventDispatcher\EventDispatcher;
use Symfony\Component\Serializer\Annotation\Groups;
use Symfony\Component\Security\Core\User\UserInterface;
use App\Base\Annotation\Common;
use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM;

/**
 * @ApiResource()
 * @ODM\Document(repositoryClass="App\Repository\UserRepository")
 */
class User implements UserInterface
{
    /**
     * @Common(cnName="#",editType="text",listType="text")
     * @ODM\Id(strategy="INCREMENT")
     * @Groups({"user"})
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @Common(cnName="账号",editType="text",listType="text")
     * @ODM\Field()
     * @Groups({"user"})
     * @ORM\Column(type="string", length=180,name="name")
     */
    private $name;

    /**
     * @Common(cnName="角色",editType="text",listType="text")
     * @ODM\Field(type="raw")
     * @ORM\Column(type="json")
     */
    private $roles = [];

    /**
     * @Common(cnName="密码",editType="text",listType="text")
     * @ODM\Field()
     * @var string The hashed password
     * @ORM\Column(type="string", nullable=true)
     */
    private $password;

    /**
     * @Common(cnName="手机号",editType="text",listType="text")
     * @ODM\Field(nullable=true)
     * @Groups({"user"})
     * @ORM\Column(type="string", length=255, nullable=true)
     */
    private $phone;

    /**
     * @Common(cnName="头像",editType="pic",listType="text")
     * @ODM\Field(nullable=true)
     * @Groups({"user"})
     * @ORM\Column(type="string", length=255)
     */
    private $avatar = "";

    /**
     * @Common(cnName="令牌",editType="text",listType="text")
     * @ODM\Field(nullable=true)
     * @ORM\Column(type="string", length=255, nullable=true)
     */
    private $ApiToken;

    /**
     * @Common(cnName="注册时间",editType="datetime",listType="text")
     * @ODM\Field(type="date",nullable=true)
     * @Groups({"user"})
     * @ORM\Column(type="datetime",nullable=true)
     */
    private $createAt;

    /**
     * @Common(cnName="OpenId",editType="text",listType="text")
     * @ODM\Field(nullable=true)
     * @Groups({"user"})
     * @ORM\Column(type="string", length=255, nullable=true)
     */
    private $openid;

    /**
     * @Common(cnName="UnionId",editType="text",listType="text")
     * @ODM\Field(nullable=true)
     * @ORM\Column(type="string", length=255, nullable=true)
     */
    private $unionid;

    /**
     * @Common(cnName="是否拉黑",editType="switch",listType="text")
     * @ODM\Field(type="boolean",nullable=true)
     * @ORM\Column(type="boolean", nullable=true)
     */
    private $isBan;

    /**
     * @Common(cnName="优惠券",editType="entity",listType="text")
     * @ODM\ReferenceMany(targetDocument="App\Entity\SalesUserJuan", mappedBy="user", orphanRemoval=true)
     * @ORM\OneToMany(targetEntity="App\Entity\SalesUserJuan", mappedBy="user", orphanRemoval=true)
     */
    private $juans;

    /**
     * @ODM\ReferenceMany(targetDocument="App\Entity\GiftLog", mappedBy="user", orphanRemoval=true,reference=true)
     * @ORM\OneToMany(targetEntity="App\Entity\GiftLog", mappedBy="user", orphanRemoval=true)
     */
    private $giftLogs;

    /**
     * @Common(cnName="推荐人",editType="entity",listType="text")
     * @ODM\ReferenceOne(targetDocument="App\Entity\User", inversedBy="sons")
     * @ORM\ManyToOne(targetEntity="App\Entity\User", inversedBy="sons")
     */
    private $parent;

    /**
     * @ODM\ReferenceMany(targetDocument="App\Entity\User", mappedBy="parent")
     * @ORM\OneToMany(targetEntity="App\Entity\User", mappedBy="parent")
     */
    private $sons;


    public function __construct()
    {
        $this->juans = new ArrayCollection();
        $this->giftLogs = new ArrayCollection();
        $this->sons = new ArrayCollection();
    }


    public function getId(): ?int
    {
        return $this->id;
    }

    public function getName(): ?string
    {
        return $this->name;
    }

    public function setName(string $name): self
    {
        $this->name = $name;

        return $this;
    }

    /**
     * A visual identifier that represents this user.
     *
     * @see UserInterface
     */
    public function getUsername(): string
    {
        return (string) $this->name;
    }

    /**
     * @see UserInterface
     */
    public function getRoles(): array
    {
        $roles = $this->roles;
        // guarantee every user at least has ROLE_USER
        $roles[] = 'ROLE_USER';

        return array_unique($roles);
    }

    public function setRoles(array $roles): self
    {
        $this->roles = $roles;

        return $this;
    }

    /**
     * @see UserInterface
     */
    public function getPassword(): string
    {
        return (string) $this->password;
    }

    public function setPassword(string $password): self
    {
        $this->password = $password;

        return $this;
    }

    /**
     * @see UserInterface
     */
    public function getSalt()
    {
        // not needed when using the "bcrypt" algorithm in security.yaml
    }

    /**
     * @see UserInterface
     */
    public function eraseCredentials()
    {
        // If you store any temporary, sensitive data on the user, clear it here
        // $this->plainPassword = null;
    }

    public function getApiToken(): ?string
    {
        return $this->ApiToken;
    }

    public function setApiToken(?string $ApiToken): self
    {
        $this->ApiToken = $ApiToken;

        return $this;
    }

    public function trigger($eventName)
    {
        $event = new UserChangeEvent($this);
        $dispatcher = new EventDispatcher();
        $dispatcher->addSubscriber(new UserSubscriber());
        $dispatcher->dispatch($event,$eventName);
    }

    public function getPhone(): ?string
    {
        return $this->phone;
    }

    public function setPhone(string $phone): self
    {
        $this->phone = $phone;

        return $this;
    }

    public function getAvatar(): ?string
    {
        return $this->avatar;
    }

    public function setAvatar(string $avatar): self
    {
        $this->avatar = $avatar;

        return $this;
    }

    public function getCreateAt(): ?\DateTimeInterface
    {
        return $this->createAt;
    }

    public function setCreateAt(\DateTimeInterface $createAt): self
    {
        $this->createAt = $createAt;

        return $this;
    }

    public function getOpenid(): ?string
    {
        return $this->openid;
    }

    public function setOpenid(?string $openid): self
    {
        $this->openid = $openid;

        return $this;
    }

    public function getUnionid(): ?string
    {
        return $this->unionid;
    }

    public function setUnionid(?string $unionid): self
    {
        $this->unionid = $unionid;

        return $this;
    }

    public function getIsBan(): ?bool
    {
        return $this->isBan;
    }

    public function setIsBan(?bool $isBan): self
    {
        $this->isBan = $isBan;

        return $this;
    }

    /**
     * @return Collection|SalesUserJuan[]
     */
    public function getJuans(): Collection
    {
        return $this->juans;
    }

    public function addJuan(SalesUserJuan $juan): self
    {
        if (!$this->juans->contains($juan)) {
            $this->juans[] = $juan;
            $juan->setUser($this);
        }

        return $this;
    }

    public function removeJuan(SalesUserJuan $juan): self
    {
        if ($this->juans->contains($juan)) {
            $this->juans->removeElement($juan);
            // set the owning side to null (unless already changed)
            if ($juan->getUser() === $this) {
                $juan->setUser(null);
            }
        }

        return $this;
    }

    /**
     * @return Collection|GiftLog[]
     */
    public function getGiftLogs(): Collection
    {
        return $this->giftLogs;
    }

    public function addGiftLog(GiftLog $giftLog): self
    {
        if (!$this->giftLogs->contains($giftLog)) {
            $this->giftLogs[] = $giftLog;
            $giftLog->setUser($this);
        }

        return $this;
    }

    public function removeGiftLog(GiftLog $giftLog): self
    {
        if ($this->giftLogs->contains($giftLog)) {
            $this->giftLogs->removeElement($giftLog);
            // set the owning side to null (unless already changed)
            if ($giftLog->getUser() === $this) {
                $giftLog->setUser(null);
            }
        }

        return $this;
    }

    public function getParent(): ?self
    {
        return $this->parent;
    }

    public function setParent(?self $parent): self
    {
        $this->parent = $parent;

        return $this;
    }

    /**
     * @return Collection|self[]
     */
    public function getSons(): Collection
    {
        return $this->sons;
    }

    public function addSon(self $son): self
    {
        if (!$this->sons->contains($son)) {
            $this->sons[] = $son;
            $son->setParent($this);
        }

        return $this;
    }

    public function removeSon(self $son): self
    {
        if ($this->sons->contains($son)) {
            $this->sons->removeElement($son);
            // set the owning side to null (unless already changed)
            if ($son->getParent() === $this) {
                $son->setParent(null);
            }
        }

        return $this;
    }
}
